home *** CD-ROM | disk | FTP | other *** search
/ CyberMycha 2005 May / CyberMycha 05-2005 (Poland).bin / Immortal / cotndemo.exe / Data1.cab / sky_shaders.fx < prev    next >
Encoding:
Text File  |  2004-11-16  |  10.9 KB  |  313 lines

  1. // Sky dome shader code
  2.  
  3. // Note that some of the sky dome code comes from the book "Shader X2: Shader Programming Tips & Tricks with DirectX 9" ed. by Engel
  4. // Code from the article: "Advanced Sky Dome Rendering" by Marco Spoerl and Kurt Pelzer
  5. // License opposite CD at end of book: "You may use the source code, techniques, and example programs
  6. // in your own commercial or private applications unless otherwise noted by additional usage agreements 
  7. // as found on the CD."
  8.  
  9. //-----------------------------------------------------------------------------
  10.  
  11. texture SunTexture;
  12. texture MoonTexture;
  13. texture MoonBumpMap;
  14. texture CloudsCubeMap;
  15. texture StarsTexture;
  16.  
  17. //-----------------------------------------------------------------------------
  18.  
  19. float4x4 WorldViewProj;
  20. float4x4 SunTexTransform;
  21. float4x4 MoonTexTransform;
  22. float4 sunlight_normal;
  23. float4 sunlight_color;
  24. float4 sun_to_moon;
  25. float4 fog_color;
  26. float star_show_amt;
  27.  
  28. // figure these out
  29. static float4 KrConsts = { 1.0f, 0.5f, 0.6f, 0.0f }; // Raleigh scattering?
  30. static float4 KmConsts = { 0.02f, 0.8f, 1.6f, 0.0f }; // Mie scattering?
  31.  
  32. //-----------------------------------------------------------------------------
  33.  
  34. // Texture sampling attributes
  35. sampler SunTextureSampler = sampler_state //!FIX does it matter if sampler2D or just sampler?
  36. {
  37.     Texture = <SunTexture>;
  38.     MinFilter = Linear;  
  39.     MagFilter = Linear;
  40. //    MipFilter = Point; // what should this be?
  41.     AddressU  = Clamp;
  42.     AddressV  = Clamp;
  43. //    AddressW  = Clamp; // want this?
  44. };
  45.  
  46. sampler MoonTextureSampler = sampler_state //!FIX does it matter if sampler2D or just sampler?
  47. {
  48.     Texture = <MoonTexture>;
  49.     MinFilter = Linear;  
  50.     MagFilter = Linear;
  51. //    MipFilter = Point; // what should this be?
  52.     AddressU  = Clamp;
  53.     AddressV  = Clamp;
  54. //    AddressW  = Clamp; // want this?
  55. };
  56.  
  57. samplerCUBE CloudsCubeMapSampler = sampler_state
  58. {
  59.     Texture = <CloudsCubeMap>;
  60.     MinFilter = Linear;
  61.     MagFilter = Linear;
  62.     MipFilter = Linear;
  63. };
  64.  
  65. sampler StarsSampler = sampler_state
  66. {
  67.     Texture = <StarsTexture>;
  68.     MinFilter = Linear;
  69.     MagFilter = Linear;
  70.     MipFilter = Linear;
  71. };
  72. //-----------------------------------------------------------------------------
  73.  
  74. // Passed in to vertex shader
  75. struct vertexInput {
  76.     float4 position                : POSITION;
  77.     float3 normal                : NORMAL;
  78. //    float4 color                : COLOR0;
  79.     float2 texCoord                : TEXCOORD0;
  80. };
  81.  
  82. struct vertexOutput {
  83.     float4 position            : POSITION;
  84.     float4 color            : COLOR0;
  85.     float4 belowHorizon        : COLOR1;
  86.     float4 sunTexCoord        : TEXCOORD0;
  87.     float4 moonTexCoord        : TEXCOORD1;
  88.     float3 eyeVector        : TEXCOORD2; 
  89.     float2 starsTexCoord    : TEXCOORD3;
  90. };
  91.  
  92. struct vertexOutputPlain {
  93.     float4 position            : POSITION;
  94.     float4 color            : COLOR0;
  95.     float4 belowHorizon        : COLOR1;
  96.     float4 sunTexCoord        : TEXCOORD0;
  97.     float4 moonTexCoord        : TEXCOORD1;
  98. };
  99.  
  100. //-----------------------------------------------------------------------------
  101. //
  102. vertexOutputPlain VS_TransformPlain(    vertexInput IN )
  103. {
  104.     vertexOutputPlain OUT;
  105.     
  106.     // Transform position to clip space
  107.     OUT.position = mul(IN.position, WorldViewProj); // don't need to set w to 1, done automatically
  108.  
  109.     // The radius of the sky dome is 10000.  So you're dividing the position on the sphere, the height,
  110.     // by the radius of the sphere, which is the sine of the angle from the viewer's point of view.
  111.     // If the point is on the horizon, the angle is zero, and sin(0) ==  0/10000.
  112.     // If the point is straight up, the angle is 90 degrees, and sin(90 deg) == 1 == 10000/10000.
  113.     // So IN.position.z/10000.0 will vary from -1 to 1, and step will vary from 0 to 2.
  114.     // We only care about positive values of IN.position.z, 'cause if it's negative, the
  115.     // color will be set to the fog color.  See below.
  116.     float step = IN.position.z/10000.0f + 1.0f; // z coord of dome as if dome radius was 50.  z-axis is perpendicular to game terrain.
  117.     
  118.     float cos_angle_from_sun = dot(IN.normal, sunlight_normal); // both should be already normalized
  119.     
  120.     // calculate fr (molecule scattering)
  121.     float fr = (cos_angle_from_sun > 0.0f) ? cos_angle_from_sun * cos_angle_from_sun : 0.0f;
  122.     
  123.     fr = fr * 0.75f + 0.75f;
  124.     
  125.     // calculate fm (aerosol scattering)
  126.     // a cosine shouldn't ever be > 1, but I'll use >= just in case of floating point inprecision
  127.     float fm = (abs(cos_angle_from_sun) >= 1.0f) ? 1.75f : 0.75f;
  128.     
  129.     // KR color of the molocules
  130.     float3 kr = KrConsts * fr;
  131.     
  132.     // KM color of the aerosols
  133.     float3 km = KmConsts * fm + kr;
  134.     //km *= 2000.0f; // pre-multiplied KrConsts & KmConsts by 2000 instead
  135.     
  136.     // scale by steps
  137.     km *= step;
  138.     
  139.     // output color
  140.     OUT.color.rgb = (IN.position.z <= 0) ? fog_color : km * sunlight_color ; // show fog color if point below horizon
  141.     OUT.color.a = 1.0f; // alpha
  142.     
  143.     float4 sunTexCoord = mul( IN.position, SunTexTransform);
  144.     
  145.     OUT.sunTexCoord = sunTexCoord;
  146.     OUT.moonTexCoord = mul(IN.position, MoonTexTransform);
  147.     
  148.     OUT.belowHorizon = (IN.position.z <= 0) ? 0 : 1; // if this part of sky dome is below the horizon, don't show sun, moon, etc.
  149.  
  150.     return OUT;
  151. }
  152.  
  153. //-----------------------------------------------------------------------------
  154.  
  155. vertexOutput VS_Transform(    vertexInput IN )
  156. {
  157.     vertexOutput OUT;
  158.     
  159.     // Transform position to clip space
  160.     OUT.position = mul(IN.position, WorldViewProj); // don't need to set w to 1, done automatically
  161.  
  162.     // The radius of the sky dome is 10000.  So you're dividing the position on the sphere, the height,
  163.     // by the radius of the sphere, which is the sine of the angle from the viewer's point of view.
  164.     // If the point is on the horizon, the angle is zero, and sin(0) ==  0/10000.
  165.     // If the point is straight up, the angle is 90 degrees, and sin(90 deg) == 1 == 10000/10000.
  166.     // So IN.position.z/10000.0 will vary from -1 to 1, and step will vary from 0 to 2.
  167.     // We only care about positive values of IN.position.z, 'cause if it's negative, the
  168.     // color will be set to the fog color.  See below.
  169.     float step = IN.position.z/10000.0f + 1.0f;//IN.texCoord.x * IN.texCoord.x; // z coord of dome as if dome radius was 50.  z-axis is perpendicular to game terrain.
  170.     
  171.     float cos_angle_from_sun = dot(IN.normal, sunlight_normal); // both should be already normalized
  172.     
  173.     // calculate fr (molecule scattering)
  174.     float fr = (cos_angle_from_sun > 0.0f) ? cos_angle_from_sun * cos_angle_from_sun : 0.0f;
  175.     
  176.     fr = fr * 0.75f + 0.75f;
  177.     
  178.     // calculate fm (aerosol scattering)
  179.     // a cosine shouldn't ever be > 1, but I'll use >= just in case of floating point inprecision
  180.     float fm = (abs(cos_angle_from_sun) >= 1.0f) ? 1.75f : 0.75f;
  181.     
  182.     // KR color of the molocules
  183.     float3 kr = KrConsts * fr;
  184.     
  185.     // KM color of the aerosols
  186.     float3 km = KmConsts * fm + kr;
  187.     //km *= 2000.0f; // pre-multiplied KrConsts & KmConsts by 2000 instead
  188.     
  189.     // scale by steps
  190.     km *= step;
  191.     
  192.     // output color
  193.     OUT.color.rgb = (IN.position.z <= 0) ? fog_color : km * sunlight_color ; // show fog color if point below horizon
  194.     OUT.color.a = 1.0f; // alpha
  195.     
  196.     float4 sunTexCoord = mul( IN.position, SunTexTransform);
  197.     
  198.     OUT.sunTexCoord = sunTexCoord;
  199.     OUT.moonTexCoord = mul(IN.position, MoonTexTransform);
  200.     
  201.     // clouds
  202.     OUT.eyeVector = IN.position.xzy; //swap z & y (in Empire Earth code, Z points up, not Y)
  203.     OUT.belowHorizon = (IN.position.z <= 0) ? 0 : 1; // if this part of sky dome is below the horizon, don't show sun, moon, etc.
  204.     
  205.     OUT.starsTexCoord = IN.texCoord;
  206.  
  207.     return OUT;
  208. }
  209. //-----------------------------------
  210.  
  211. // Simple pixel shader.
  212. float4 PS_ColorPlain( vertexOutput IN ): COLOR
  213. {
  214.     float belowHorizon = IN.belowHorizon; // if this part of sky dome is below the horizon, don't show sun, moon, etc.
  215.     float4 sun = tex2D(SunTextureSampler, IN.sunTexCoord) ;
  216.     float4 moon = tex2D(MoonTextureSampler, IN.moonTexCoord);
  217.     
  218.     float4 color = sun * (1 - IN.color) + IN.color + moon ; // where sun texture is white, show white.  If sun texture is black, show original color.    
  219.     color = saturate(color);
  220.  
  221.     color = belowHorizon  * color + (1.0 - belowHorizon) *IN.color; // if below horizon, don't show sun, moon
  222. //    color = saturate(color);
  223.  
  224.     return color;
  225. }
  226.  
  227. //-----------------------------------
  228.  
  229. // Simple pixel shader.
  230. float4 PS_Color( vertexOutput IN ): COLOR
  231. {
  232.     float4 color = IN.color;
  233.     float belowHorizon = IN.belowHorizon; // if this part of sky dome is below the horizon, don't show sun, moon, etc.
  234.     float4 sun = tex2D(SunTextureSampler, IN.sunTexCoord) ;
  235.     float4 moon = tex2D(MoonTextureSampler, IN.moonTexCoord);
  236.     float4 stars = tex2D(StarsSampler, IN.starsTexCoord);
  237.     // what about alpha?
  238.     
  239.     const float star_fade_in_limit = 0.5f; 
  240.     star_show_amt = saturate(star_show_amt * star_fade_in_limit); // makes compiler happy - next instruction requires fewer instructions
  241.     color = (1.0 - star_show_amt) * color + star_show_amt * stars; // HLSL lerp function not allowed in PS 1.1 ?! ASM lrp is!
  242.     color = saturate(color); // makes compiler happy, can generate a complement on next line
  243.     color = sun * (1 - color) + color + moon ; // where sun texture is white, show white.  If sun texture is black, show original color.    
  244.     //color = saturate(color);
  245.     
  246.     float4 clouds = texCUBE(CloudsCubeMapSampler , IN.eyeVector);
  247.     //clouds = saturate(clouds); // makes compiler happy
  248.     
  249.     // Composite the cloud environment map
  250.     color = (clouds.a * clouds) + ((1.0 - clouds.a) * color);
  251.     color = belowHorizon  * color + (1.0 - belowHorizon) *IN.color; // if below horizon, don't show sun, moon, stars
  252. //    color = saturate(color);
  253.  
  254.     return color;
  255. }
  256.  
  257. //-----------------------------------------------------------------------------
  258.  
  259.  
  260. technique RenderPlainSky
  261. {
  262.     pass P0
  263.     {
  264.         VertexShader = compile vs_1_1 VS_TransformPlain();
  265.         PixelShader = compile ps_1_1 PS_ColorPlain();
  266.  
  267.         CullMode         = None;
  268.     
  269.         Texture[0] = <SunTexture>;        
  270.         Texture[1] = <MoonTexture>;
  271.         TexCoordIndex[0] = 0;
  272.         TexCoordIndex[1] = 1;
  273.         TextureTransformFlags[0] = Projected;
  274.         TextureTransformFlags[1] = Projected;
  275.         
  276.         //FillMode = Wireframe;
  277.  
  278.         FogEnable = False;
  279.         ZEnable            = True;
  280.         ZWriteEnable = False;
  281.     }
  282. }
  283.  
  284. technique RenderSky
  285. {
  286.     pass P0
  287.     {
  288.         VertexShader = compile vs_1_1 VS_Transform();
  289.         PixelShader = compile ps_1_2 PS_Color();
  290.  
  291.         CullMode         = None;
  292.     
  293.         Texture[0] = <SunTexture>;        
  294.         Texture[1] = <MoonTexture>;
  295.         Texture[2] = <CloudsCubeMap>;
  296.         Texture[3] = <StarsTexture>;
  297.         TexCoordIndex[0] = 0;
  298.         TexCoordIndex[1] = 1;
  299.         TexCoordIndex[2] = 2;
  300.         TexCoordIndex[3] = 3;
  301.         TextureTransformFlags[0] = Projected;
  302.         TextureTransformFlags[1] = Projected;
  303.         TextureTransformFlags[2] = Disable;
  304.         TextureTransformFlags[3] = Disable;
  305.         
  306.         //FillMode = Wireframe;
  307.  
  308.         FogEnable = False;
  309.         ZEnable            = True;
  310.         ZWriteEnable = False;
  311.     }
  312. }
  313.